/**
 * Copyright 2009-2011 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.myjung.model;

import java.util.ArrayList;
import java.util.List;

import net.myjung.Myjung;
import net.myjung.model.annotation.MdlField;
import net.myjung.util.ListMap;

/**
 * @author Steve M. Jung
 */
@SuppressWarnings("serial")
public class ExtensibleObject extends BaseObject {
	@MdlField
	private boolean extAttrsChanged = false;
	@MdlField
	private List<Property> extendedAttributes;
	@MdlField
	private ListMap<String, Property> extAttrMap = new ListMap<String, Property>();
	@MdlField
	private boolean extElemsChanged = false;
	@MdlField
	private List<Property> extendedElements;
	@MdlField
	private ListMap<String, Object> extElemMap = new ListMap<String, Object>();
	public List<Property> getExtendedAttributes() {
		if (!extAttrsChanged)
			return extendedAttributes;
		if (extAttrMap.isEmpty())
			return null;
		this.extendedAttributes = extAttrMap.valueList();
		extAttrsChanged = false;
		return this.extendedAttributes;
	}
	public void setExtendedAttributes(List<Property> extAttrs) {
		this.extendedAttributes = extAttrs;
		this.extAttrMap.clear();
		if (Myjung.isEmpty(extAttrs))
			return;
		for (Property extAttr : extAttrs) {
			String name = extAttr.getName();
			extAttrMap.put(name, extAttr);
		}
		extAttrsChanged = false;
	}
	public String getExtendedAttributeValue(String name) {
		if (!extAttrMap.containsKey(name))
			return null;
		Property obj = (Property) extAttrMap.get(name);
		String value = obj.getValue();
		return value;
	}
	public void setExtendedAttributeValue(String name, String value) {
		this.extAttrsChanged = true;
		if (name == null)
			return;
		if (value == null && extAttrMap.containsKey(name)) {
			extAttrMap.remove(name);
			return;
		}
		extAttrMap.put(name, new Property(name, value));
	}
	public List<Property> getExtendedElements() {
		if (!extElemsChanged)
			return extendedElements;
		if (extElemMap.isEmpty())
			return null;
		List<Property> list = new ArrayList<Property>();
		List<String> keyList = extElemMap.keyList();
		for (String key : keyList) {
			Object value = extElemMap.get(key);
			if (value instanceof Property) {
				list.add((Property) value);
			} else if (value instanceof List<?>) {
				List<?> valueList = (List<?>) value;
				for (Object obj : valueList)
					list.add((Property) obj);
			}
		}
		this.extendedElements = list;
		extElemsChanged = false;
		return list;
	}
	@SuppressWarnings("unchecked")
	public void setExtendedElements(List<Property> extendedElements) {
		this.extendedElements = extendedElements;
		this.extElemMap.clear();
		if (Myjung.isEmpty(extendedElements))
			return;
		for (Property extendedElement : extendedElements) {
			String name = extendedElement.getName();
			if (extElemMap.containsKey(name)) {
				Object obj = extElemMap.get(name);
				if (obj instanceof Property) {
					List<Property> list = new ArrayList<Property>();
					list.add((Property) obj);
					list.add(extendedElement);
					extElemMap.put(name, list);
				} else if (obj instanceof List<?>) {
					List<Property> list = (List<Property>) obj;
					list.add(extendedElement);
				}
			} else {
				extElemMap.put(name, extendedElement);
			}
		}
		extElemsChanged = false;
	}
	@SuppressWarnings("unchecked")
	public String getExtendedElementValue(String name) {
		if (!extElemMap.containsKey(name))
			return null;

		Object obj = extElemMap.get(name);
		String value = null;
		if (obj instanceof Property) {
			Property extElem = (Property) obj;
			value = extElem.getValue();
		} else if (obj instanceof List<?>) {
			List<Property> extElemList = (List<Property>) obj;
			if (!extElemList.isEmpty()) {
				Property extElem = (Property) extElemList.get(0);
				value = extElem.getValue();
			}
		}
		return value;
	}
	public void setExtendedElementValue(String name, String value) {
		this.extElemsChanged = true;
		if (name == null)
			return;
		if (Myjung.isEmpty(value)) {
			if (extElemMap.containsKey(name))
				extElemMap.remove(name);
			return;
		}
		extElemMap.put(name, new Property(name, value));
	}
	@SuppressWarnings("unchecked")
	public List<String> getExtendedElementValues(String name) {
		if (extElemMap.containsKey(name)) {
			Object obj = extElemMap.get(name);
			List<String> values = null;
			if (obj instanceof Property) {
				Property extElem = (Property) obj;
				values = new ArrayList<String>();
				values.add(extElem.getValue());
			} else if (obj instanceof List<?>) {
				List<Property> extElemList = (List<Property>) obj;
				if (!extElemList.isEmpty()) {
					values = new ArrayList<String>();
					for (Property extElem : extElemList) {
						values.add(extElem.getValue());
					}
				}
			}
			return values;
		}
		return null;
	}
	public void setExtendedElementValues(String name, List<String> values) {
		this.extElemsChanged = true;
		if (Myjung.isEmpty(values)) {
			this.setExtendedElementValue(name, null);
			return;
		}

		if (values.size() == 1) {
			this.setExtendedElementValue(name, values.get(0));
			return;
		}

		List<Property> list = new ArrayList<Property>();
		for (String value : values) {
			Property obj = new Property(name, value);
			list.add(obj);
		}
		extElemMap.put(name, list);
	}
	public void addExtendedElement(Property extendedElement) {
		if (extendedElement == null)
			return;
		List<Property> extElems = this.getExtendedElements();
		if (extElems == null)
			extElems = new ArrayList<Property>();
		extElems.add(extendedElement);
		this.setExtendedElements(extElems);
	}

	//	@Override
	//	protected void appendAttributesString(StringBuffer buf, List<Field> aList) {
	//		super.appendAttributesString(buf, aList);
	////		List<Property> extAttrs = getExtendedAttributes();
	////		if (!Myjung.isEmpty(extAttrs)) {
	////			String fName;
	////			String fValue;
	////			for (Property prop:extAttrs) {
	////				fName = prop.getName();
	////				fValue = prop.getValue();
	////				if (Myjung.isEmpty(fName) || fValue == null)
	////					continue;
	////				buf.append(" ").append(fName).append("=\"").append(fValue).append("\"");
	////			}
	////		}
	//	}
}
